﻿using System;
using System.Collections.Generic;
using System.Data.SQLite;
using CWB.Common.Constant;
using CWB.Common.DTO;
using CWB.Common.Logging;
using CWB.Common.Utilities;
using CWB.Web.Models;
using System.Runtime.Serialization;
using System.Linq;
using CWB.Web.CacheLayer;

namespace CWB.Web.DB
{
    public class DbModuleAgent
    {
        public int sn;
        public int uplinesn;
        public int Position;
        public int Possess;
        public string Notes;
        public string Username;
        public string Loginid;
        public decimal CreditLimit;
        public int Status;

        public string Password;
        public string chk;

        public List<AgentProdItem> ProdItems;

        public DbModuleAgent()
        {
            sn = 0;
            uplinesn = 0;
            Position = 0;
            Possess = 0;
            Notes = "";
            Username = "";
            Loginid = "";
            CreditLimit = 0;
            Status = 0;
            Password = "";
            chk = "";
            ProdItems = new List<AgentProdItem>() { };
        }
    }

    public class AgentProdItem
    {
        public int prodSN;
        public string prodName;
        public string prodid;
        public int price;
    }

    public class DbTableAgent : BaseDBA
    {
        private readonly static ISysLog log = SysLog.GetLogger(typeof(DbTableAgent));

        public DbTableAgent()
        {
            base.init(typeof(DbTableAgent).ToString(), DataBaseName.Org);
        }

        private List<DbModuleAgent> dr2DbModuleAgent(SQLiteDataReader sdr)
        {
            List<DbModuleAgent> listbbu = new List<DbModuleAgent>() { };
            if (sdr.HasRows)
            {
                while (sdr.Read())
                {
                    listbbu.Add(new DbModuleAgent()
                    {
                        sn = Convert.ToInt16(sdr["sn"].ToString()),
                        Possess = Convert.ToInt16(sdr["possess"].ToString()),
                        Status = Convert.ToInt16(sdr["status"].ToString()),
                        Position = Convert.ToInt16(sdr["position"].ToString()),
                        chk = sdr["chk"].ToString(),
                        Notes = sdr["notes"].ToString(),
                        Username = sdr["username"].ToString(),
                        Loginid = sdr["loginid"].ToString(),
                        Password = sdr["pwd"].ToString(),
                        CreditLimit = Convert.ToDecimal(sdr["creditlimit"].ToString()),
                        uplinesn = Convert.ToInt16(sdr["uplinesn"].ToString())
                    });
                }
            }
            return listbbu;
        }

        public List<int> getAllDownLineSN(int agentSN, int position, string searchValue)
        {
            List<int> rtn = new List<int>() { };
            //get current level
            SqlCommandObj sco = new SqlCommandObj()
            {
                commandText = "Select position from Agent where sn = " + agentSN
            };
            int currentPosition = ExecuteCount(sco);

            if (currentPosition >= position - 1)
            {
                //meet target.
                //get downline sn.
                string sqlWhere = string.Format(" where uplinesn = {0} and position = {1} ", agentSN, position); ;
                List<SQLiteParameter> sqlPara = new List<SQLiteParameter>() { };
                if (!string.IsNullOrEmpty(searchValue))
                {
                    if (searchValue.Contains("*"))
                    {
                        searchValue = searchValue.Replace("*", "%");
                        sqlWhere += " and username like @value ";
                    }
                    else
                    {
                        sqlWhere += " and username = @value ";
                    }
                    sqlPara.Add(new SQLiteParameter("@value", searchValue.Trim()));
                }
                
                sco = new SqlCommandObj()
                {
                    commandText = string.Format("Select sn from Agent {0}", sqlWhere),
                    paraList = sqlPara
                };
                List<int> intTemp = new List<int>() { };
                using (SQLiteDataReader dr = ExecuteReader(sco))
                {
                    if (dr.HasRows)
                    {
                        while (dr.Read())
                        {
                            intTemp.Add(Convert.ToInt16(dr["sn"].ToString()));
                        }
                    }
                }

                return intTemp;
            }
            else
            {
                //get downline sn.
                sco = new SqlCommandObj()
                {
                    commandText = "Select sn from Agent where uplinesn = " + agentSN
                };
                List<int> intTemp = new List<int>() { };
                using (SQLiteDataReader dr = ExecuteReader(sco))
                {
                    if (dr.HasRows)
                    {
                        while (dr.Read())
                        {
                            intTemp.Add(Convert.ToInt16(dr["sn"].ToString()));
                        }
                    }
                }

                if (intTemp.Count > 0)
                {
                    foreach (int sn in intTemp)
                    {
                        rtn.AddRange(getAllDownLineSN(sn, position, searchValue));
                    }
                }
            }
            return rtn;
        }

        public int DeleteAgentuBySn(int sn)
        {
            //Check hierarchy
            bool chkHierarchyPassed = chkIsInHierarchy(sn);
            if (chkHierarchyPassed)
            {
                int rtn = 0;
                SqlCommandObj sco = new SqlCommandObj();
                //need to check is there are any downline under the agent.
                sco.commandText = "select count(*) as rcnt from Agent where uplinesn = @sn";
                sco.paraList = new List<SQLiteParameter>()
            {
                new SQLiteParameter("@sn", sn)
            };

                int rcnt = ExecuteCount(sco);
                if (rcnt == 0)
                {
                    sco.commandText = "delete from AgentProdItems where AgentSN = @sn;";
                    try
                    {
                        startTrain();
                        ExecuteNonQuery(sco);
                        sco.commandText = "delete from Agent where sn = @sn;";
                        if (ExecuteNonQuery(sco) > 0)
                        {
                            rtn = 1;
                        }
                        else
                        {
                            rtn = -1;
                        }
                        commitTrain();
                    }
                    catch (Exception ex)
                    {
                        log.Exception(ex);
                        rollbackTrain();
                        rtn = -9;
                    }
                }
                else
                {
                    rtn = -2;
                }
                return rtn;
            }
            else
            {
                return -1;
            }
        }


        public bool LoginIdIsExist(string LoginId, int position)
        {
            SqlCommandObj sco = new SqlCommandObj();
            sco.commandText = "select count(*) as rcnt from Agent where loginid = @loginid and position = @position;";
            sco.paraList = new List<SQLiteParameter>()
            {
                new SQLiteParameter("@loginid", LoginId),
                new SQLiteParameter("@position", position.ToString())
            };
            int nums = ExecuteCount(sco);

            return (nums > 0);
        }

        private bool doChkIsInHierarchy(int SelfSN, int targetSN)
        {
            bool chkHierarchyPassed = false;
            if (SelfSN == targetSN)
            {
                chkHierarchyPassed = true;
            }
            else
            {
                SqlCommandObj sco = new SqlCommandObj()
                {
                    commandText = "Select uplinesn from Agent where sn = @targetSN",
                    paraList = new List<SQLiteParameter>()
                    {
                        new SQLiteParameter("@targetSN", targetSN)
                    }
                };
                int uplinesn = ExecuteCount(sco);

                if (uplinesn == 0)
                {
                    return false;
                }
                else
                {
                    chkHierarchyPassed = doChkIsInHierarchy(SelfSN, uplinesn);
                }
            }
            return chkHierarchyPassed;
        }

        public bool chkIsInHierarchy(int targetSN)
        {
            //Check hierarchy
            Trading trading = new SessionData().trading;
            bool chkHierarchyPassed = (trading.loginType == LoginType.Bo);
            if (chkHierarchyPassed == false && trading != null && trading.sn != null)
            {
                chkHierarchyPassed = doChkIsInHierarchy(trading.sn, targetSN);
            }
            return chkHierarchyPassed;
        }

        public List<DbModuleAgent> getAgentDbModule(ref Paging pg, string searchValue, int parentSN, int position, DBSortingPara dbSortingPara)
        {
            List<DbModuleAgent> listProdItem = new List<DbModuleAgent>() { };

            Trading trading = new SessionData().trading;
            //Check hierarchy
            bool chkHierarchyPassed = chkIsInHierarchy(parentSN);

            if (chkHierarchyPassed)
            {
                string sqlMain = "Select * from Agent";
                string sqlWhere = string.Format(" Where position = {0}", position);
                string sqlOrderby = default(string);
                List<SQLiteParameter> sqlPara = new List<SQLiteParameter>() { };

                if (parentSN > 0)
                {
                    sqlWhere += string.Format(" and uplinesn = {0}", parentSN);
                }

                if (!string.IsNullOrEmpty(searchValue))
                {
                    if (searchValue.Contains("*"))
                    {
                        searchValue = searchValue.Replace("*", "%");
                        sqlWhere += " and (username like @value or loginid like @value)";
                    }
                    else
                    {
                        sqlWhere += " and (username = @value or loginid = @value)";
                    }
                    sqlPara.Add(new SQLiteParameter("@value", searchValue.Trim()));
                }
                sqlOrderby = dbSortingPara.getOrderByHLQ();

                //get totalRecord
                SqlCommandObj sco = new SqlCommandObj();
                sco.commandText = sqlMain.Replace(" * ", " count(*) as rcnt ") + sqlWhere;
                sco.paraList = sqlPara;
                int count = ExecuteCount(sco);
                pg.totalRecord = count;

                //get data
                sco.commandText = string.Format("{0} {1} {2} {3}", sqlMain, sqlWhere, sqlOrderby, pg.getLimitSql());
                using (SQLiteDataReader dr = ExecuteReader(sco))
                {
                    listProdItem = dr2DbModuleAgent(dr);
                }
            }

            return listProdItem;
        }

        public List<DbModuleAgent> getAgentByParentSN(ref Paging pg, int parentSN, DBSortingPara dbSortingPara)
        {
            string sqlMain = "Select * from Agent";
            string sqlWehre = default(string);
            string sqlOrderby = default(string);
            List<SQLiteParameter> sqlPara = new List<SQLiteParameter>() { };
            if (parentSN > 0)
            {
                sqlWehre = string.Format(" Where sn = {0} ", parentSN);
            }
            else
            {
                sqlWehre = "";
            }

            sqlOrderby = dbSortingPara.getOrderByHLQ();

            //get totalRecord
            SqlCommandObj sco = new SqlCommandObj();
            sco.commandText = sqlMain.Replace(" * ", " count(*) as rcnt ");
            sco.paraList = sqlPara;
            int count = ExecuteCount(sco);
            pg.totalRecord = count;

            //get data
            sco.commandText = string.Format("{0} {1} {2} {3}", sqlMain, sqlWehre, sqlOrderby, pg.getLimitSql());
            List<DbModuleAgent> listProdItem = new List<DbModuleAgent>() { };
            using (SQLiteDataReader dr = ExecuteReader(sco))
            {
                listProdItem = dr2DbModuleAgent(dr);
            }

            return listProdItem;
        }


        public DbModuleAgent getAgentbySn(int sn)
        {
            DbModuleAgent rtnobj = new DbModuleAgent();

            if (sn > 0)
            {
                string sql = "Select * from Agent where sn = @sn";
                List<SQLiteParameter> sqlPara = new List<SQLiteParameter>() { };
                sqlPara.Add(new SQLiteParameter("@sn", sn));

                SqlCommandObj sco = new SqlCommandObj();
                sco.commandText = sql;
                sco.paraList = sqlPara;
                using (SQLiteDataReader dr = ExecuteReader(sco))
                {
                    var listobj = dr2DbModuleAgent(dr);
                    if (listobj.Count > 0)
                    {
                        rtnobj = listobj[0];
                    }
                    else
                    {
                        rtnobj = new DbModuleAgent() { };
                    }
                }

                try
                {
                    sco.commandText = "Select proditems.sn, proditems.prodid, proditems.prodname, AgentProdItems.Price from proditems join AgentProdItems on proditems.sn = AgentProdItems.ProdItemSN where AgentProdItems.AgentSN = @sn";
                    List<AgentProdItem> proditems = new List<AgentProdItem>() { };
                    using (SQLiteDataReader psn = ExecuteReader(sco))
                    {
                        if (psn.HasRows)
                        {
                            while (psn.Read())
                            {
                                proditems.Add(new AgentProdItem()
                                {
                                    price = Convert.ToInt16(psn["Price"].ToString()),
                                    prodid = psn["prodid"].ToString(),
                                    prodName = psn["prodname"].ToString(),
                                    prodSN = Convert.ToInt16(psn["sn"].ToString())
                                });
                            }
                        }
                    }
                    rtnobj.ProdItems = proditems;
                }
                catch (Exception ex)
                {
                    log.Exception(ex);
                }
            }
            return rtnobj;
        }

        public bool createAgent(DbModuleAgent obj)
        {
            //deal with agent information
            //check is the login is exist.
            if (LoginIdIsExist(obj.Loginid, obj.Position))
            {
                log.Debug(string.Format("LoginId {0} is existing.", obj.Loginid));
                return false;
            }
            else
            {
                startTrain();
                SqlCommandObj sco = new SqlCommandObj();
                sco.commandText = "insert into Agent (uplinesn, possess, position, notes, username, loginid, pwd, creditlimit, status) values (@uplinesn, @Possess, @Position, @notes, @username, @loginid, @password, @creditlimit, 1)";
                sco.paraList = new List<SQLiteParameter>()
                {
                    new SQLiteParameter("@uplinesn", obj.uplinesn),
                    new SQLiteParameter("@Possess", obj.Possess),
                    new SQLiteParameter("@Position", obj.Position),
                    new SQLiteParameter("@notes", obj.Notes),
                    new SQLiteParameter("@username", obj.Username),
                    new SQLiteParameter("@loginid", obj.Loginid),
                    new SQLiteParameter("@password", obj.Password),
                    new SQLiteParameter("@creditlimit", obj.CreditLimit)
                };
                if (ExecuteNonQuery(sco) > 0)
                {
                    if (obj.ProdItems.Count > 0)
                    {
                        //get next PK
                        sco.commandText = "select last_insert_rowid();";
                        sco.paraList = null;
                        int sn = ExecuteCount(sco);
                        foreach (AgentProdItem pp in obj.ProdItems)
                        {
                            sco.commandText = "insert into AgentProdItems (Price, ProdItemSN, AgentSN) values (@Price, @ProdItemSN, @AgentSN)";
                            sco.paraList = new List<SQLiteParameter>()
                            {
                                new SQLiteParameter("@Price", pp.price),
                                new SQLiteParameter("@ProdItemSN", pp.prodSN),
                                new SQLiteParameter("@AgentSN", sn)
                            };
                            ExecuteNonQuery(sco);
                        }
                    }
                    commitTrain();
                    return true;
                }
                else
                {
                    rollbackTrain();
                    return false;
                }
            }
        }

        public bool updateAgent(DbModuleAgent obj)
        {
            //check is under Hierarchy.
            SessionData sd = new SessionData();
            if (sd.trading.loginType == LoginType.Agent)
            {
            }


            startTrain();
            SqlCommandObj sco = new SqlCommandObj();
            sco.commandText = "update Agent set possess = @Possess, notes = @notes, username = @username, creditlimit = @creditlimit where sn = @sn";
            sco.paraList = new List<SQLiteParameter>()
            {
                new SQLiteParameter("@Possess", obj.Possess),
                new SQLiteParameter("@notes", obj.Notes),
                new SQLiteParameter("@username", obj.Username),
                new SQLiteParameter("@creditlimit", obj.CreditLimit),
                new SQLiteParameter("@sn", obj.sn)
            };
            if (ExecuteNonQuery(sco) > 0)
            {
                //get next PK
                sco.commandText = "delete from AgentProdItems where AgentSN = @sn";
                sco.paraList = new List<SQLiteParameter>()
                {
                    new SQLiteParameter("@sn", obj.sn)
                };
                ExecuteNonQuery(sco);
                foreach (AgentProdItem pp in obj.ProdItems)
                {
                    sco.commandText = "insert into AgentProdItems (Price, ProdItemSN, AgentSN) values (@Price, @ProdItemSN, @AgentSN)";
                    sco.paraList = new List<SQLiteParameter>()
                            {
                                new SQLiteParameter("@Price", pp.price),
                                new SQLiteParameter("@ProdItemSN", pp.prodSN),
                                new SQLiteParameter("@AgentSN", obj.sn)
                            };
                    ExecuteNonQuery(sco);
                }
                commitTrain();
                return true;
            }
            else
            {
                rollbackTrain();
                return false;
            }
        }

        public int getRangeBySN(int CurrentSN, int ParentSN)
        {
            try
            {
                if (CurrentSN + ParentSN == 0)
                {
                    //Create MA
                    return 100;
                }
                else if (CurrentSN == 0 && ParentSN > 0)
                {
                    //Create AG
                    int UpLinePossess = getUplinePossess(ParentSN, true);
                    return (100 - UpLinePossess);
                }
                else 
                {
                    //Update MA
                    int UpLinePossess = 0;
                    int DownLinePossess = 0;
                    int Possess = 0;
                    // get upline settings
                    UpLinePossess = getUplinePossess(CurrentSN, true);
                    // get down line settings
                    DownLinePossess = getMaxDownLinePossess(CurrentSN);
                    // get self possess.
                    Possess = getUplinePossess(CurrentSN, false);
                    return (100 - UpLinePossess - DownLinePossess + Possess);
                }
            }
            catch (Exception ex)
            {
                log.Exception(ex);
            }
            return 0;
        }


        private int getSelfPossess(int CurrentAgentSn)
        {
            return getUplinePossess(CurrentAgentSn, false);
        }

        //include current agent.
        private int getUplinePossess(int currentAgentSn, bool recursion)
        {
            int uplinesn = 0;
            int uplinepossess = 0;

            //Get Upline sn and upline's possess.
            SqlCommandObj sco = new SqlCommandObj();
            sco.commandText = "select uplinesn, possess from Agent where sn = @sn";
            sco.paraList = new List<SQLiteParameter>()
            {
                new SQLiteParameter("@sn", currentAgentSn)
            };
            using (SQLiteDataReader dr = ExecuteReader(sco))
            {
                if (dr.HasRows)
                {
                    if (dr.Read())
                    {
                        uplinesn = Convert.ToInt16(dr["uplinesn"].ToString());
                        uplinepossess = Convert.ToInt16(dr["possess"].ToString());
                    }
                }
            }

            if (uplinesn > 0 && recursion)
            {
                uplinepossess = uplinepossess + getUplinePossess(uplinesn, recursion);
            }
            return uplinepossess;
        }


        //exclude current agent
        private int getMaxDownLinePossess(int currentAgentSn)
        {
            int rtnTotalPossess = 0;
            //Get downline sn and downline's possess.
            SqlCommandObj sco = new SqlCommandObj();
            sco.commandText = "select sn, possess from Agent where uplinesn = (@sn)";
            sco.paraList = new List<SQLiteParameter>()
            {
                new SQLiteParameter("@sn", currentAgentSn)
            };

            //List<KeyValuePair<int, int>> drinfo = new List<KeyValuePair<int, int>>() { };
            Dictionary<int, int> drinfo = new Dictionary<int, int>() { };

            using (SQLiteDataReader dr = ExecuteReader(sco))
            {
                if (dr.HasRows)
                {
                    while (dr.Read())
                    {
                        int downlinesn = Convert.ToInt16(dr["sn"].ToString());
                        int TotalPossess  = Convert.ToInt16(dr["possess"].ToString());
                        KeyValuePair<int, int> kdr = new KeyValuePair<int, int>() { };
                        drinfo.Add(downlinesn, TotalPossess);
                    }
                }
            }

            foreach (var kvp in drinfo.Keys.ToArray())
            {
                drinfo[kvp] += getMaxDownLinePossess(kvp);
                if (rtnTotalPossess < drinfo[kvp])
                {
                    rtnTotalPossess = drinfo[kvp];
                }
            }

            return rtnTotalPossess;
        }

        public int getPositionOfParent(int parentAgentSN)
        {
            int position = 0;
            if (parentAgentSN > 0)
            {
                SqlCommandObj sco = new SqlCommandObj();
                sco.commandText = "select position from Agent where sn = @sn";
                sco.paraList = new List<SQLiteParameter>()
                    {
                        new SQLiteParameter("@sn", parentAgentSN)
                    };
                using (SQLiteDataReader dr = ExecuteReader(sco))
                {
                    if (dr.HasRows)
                    {
                        if (dr.Read())
                        {
                            position = Convert.ToInt16(dr["position"]);
                        }
                    }
                }
            }
            return position;
        }

        public bool VerifyAgentLogin(string username, string password, out int AgentSN)
        {
            AgentSN = 0;
            bool rtn = false;
            SqlCommandObj sco = new SqlCommandObj()
            {
                commandText = "select sn from Agent where loginid = @username and pwd = @password;",
                paraList = new List<SQLiteParameter>()
                {
                    new SQLiteParameter("@username", username),
                    new SQLiteParameter("@password", password)
                }
            };

            using (SQLiteDataReader dr = ExecuteReader(sco))
            {
                if (dr.HasRows)
                {
                    if (dr.Read())
                    {
                        AgentSN = Convert.ToInt16(dr["sn"]);
                        rtn = true;
                    }
                }
            }
            return rtn;
        }

        public void UpdateAgentChk(DbModuleAgent dma)
        {
            SqlCommandObj sco = new SqlCommandObj()
            {
                commandText = "update Agent set chk = @chk where sn = @sn",
                paraList = new List<SQLiteParameter>()
                {
                    new SQLiteParameter("@chk", dma.chk),
                    new SQLiteParameter("@sn", dma.sn)
                }
            };
            ExecuteNonQuery(sco);
            AgentCache.Add(dma);
        }

        public void RemoveAgentChk(string LoginId)
        {
            CWB.Web.CacheLayer.AgentCache.AgentUserCacheInfo aginfo = AgentCache.Get(LoginId);
            SqlCommandObj sco = new SqlCommandObj()
            {
                commandText = "update Agent set chk = '' where sn = @sn",
                paraList = new List<SQLiteParameter>()
                {
                    new SQLiteParameter("@sn", aginfo.u.Loginid)
                }
            };
            ExecuteNonQuery(sco);
            AgentCache.Remove(LoginId);
        }

        public ReturnCode updatePassword(int sn, string newpad, string oldpwd)
        {
            //Check hierarchy
            bool chkHierarchyPassed = chkIsInHierarchy(sn);

            if (chkHierarchyPassed)
            {
                bool pwdChecked = false;
                List<SQLiteParameter> paraList = new List<SQLiteParameter>() { };
                paraList.Add(new SQLiteParameter("@sn", sn));
                paraList.Add(new SQLiteParameter("@password", oldpwd));

                if (!string.IsNullOrEmpty(oldpwd))
                {
                    //Need verify old pwd is matched.
                    SqlCommandObj sco = new SqlCommandObj() { };
                    sco.commandText = "select count(*) as rcnt from Agent where sn = @sn and pwd = @password;";
                    sco.paraList = paraList;
                    int rcnt = ExecuteCount(sco);
                    if (rcnt > 0)
                    {
                        pwdChecked = true;
                    }
                }
                else
                {
                    pwdChecked = true;
                }

                if (pwdChecked)
                {
                    SqlCommandObj sco = new SqlCommandObj() { };
                    sco.commandText = "update Agent set pwd = @password where sn=@sn";
                    sco.paraList = paraList;
                    if (ExecuteNonQuery(sco) > 0)
                    {
                        return ReturnCode.Success;
                    }
                    else
                    {
                        return ReturnCode.Failed;
                    }
                }
                else
                {
                    return ReturnCode.OldPwdIncorrect;
                }
            }
            else
            {
                return ReturnCode.Failed;
            }
        }

        public List<string> getDownLineRange(int ParentSN)
        {
            List<string> usedNumber = new List<string>() { };
            List<string> rtnStrs = new List<string>() { };
            int RangeLength = 0;
            int poi = getAgentbySn(ParentSN).Position;
            switch (poi)
            {
                case 1:
                    RangeLength = 1;
                    break;
                case 2:
                    RangeLength = 2;
                    break;
                default:
                    RangeLength = 0;
                    break;
            }
            if (RangeLength > 0)
            {
                //Get all direct downline login id.
                SqlCommandObj sco = new SqlCommandObj()
                {
                    commandText = "Select loginid from Agent where uplinesn = @uplinesn",
                    paraList = new List<SQLiteParameter>()
                    {
                        new SQLiteParameter("@uplinesn", ParentSN)
                    }
                };
                SQLiteDataReader dr = ExecuteReader(sco);
                string currentLoginid = new SessionData().trading.userName;
                int maxLength = currentLoginid.Length + RangeLength;
                if (dr.HasRows)
                {
                    while (dr.Read())
                    {
                        string loginid = dr["loginid"].ToString();
                        if (loginid.Length == maxLength && loginid.IndexOf(currentLoginid) > -1)
                        {
                            string numstr = loginid.Substring(currentLoginid.Length, RangeLength);
                            int num = -1;
                            if (numstr == "00" || numstr == "0")
                            {
                                num = 0;
                            }
                            else
                            {
                                // numstr can't be pars to numeric.
                                num = Convert.ToInt16(numstr);
                                if (num == 0)
                                {
                                    num = -1;
                                }
                            }
                            if (num > -1)
                            {
                                usedNumber.Add(num.ToString(string.Format("D{0}", RangeLength)));
                            }
                        }
                    }
                }
                int max = Convert.ToInt16(Math.Pow(10, RangeLength));
                for (int i = 0; i < max; i++) 
                {
                    rtnStrs.Add(i.ToString(string.Format("D{0}", RangeLength)));
                }

                //rtnStrs = rtnStrs.Select(x => usedNumber.Contains(x.ToString())).ToList();
                var rtn = from x in rtnStrs
                          where !(from y in usedNumber
                                  select y)
                                  .Contains(x)
                          select x;
                rtnStrs = rtn.ToList();
            }
            return rtnStrs;
        }
    }
}
